package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/eiannone/keyboard"
)

var reader *bufio.Reader

// 用户自定义类型
type User struct {
	UserName        string
	Age             int
	FavouriteNumber float64
	OwnsADog        bool
}

func main() {
	reader = bufio.NewReader(os.Stdin)
	var user User

	user.UserName = readString("What's your name?")
	user.Age = readInt("How old are you?")
	user.FavouriteNumber = readFloat("What is your favourite number?")
	user.OwnsADog = readConfirm("Do you own a dog(y/n)?")

	ownDogString := "You have a dog."
	if !user.OwnsADog {
		ownDogString = "You don't have a dog."
	}

	// 使用字符串连接，但它不能进行计算
	fmt.Println("Your name is "+user.UserName+". You are", user.Age, "years old. Your favourite number is", user.FavouriteNumber, ownDogString)

	// 使用Format
	output := fmt.Sprintf("Your name is %s. You are %d years old. Your favourite number is %.2f. %s", user.UserName, user.Age, user.FavouriteNumber, ownDogString)
	fmt.Println(output)

	// 使用Printf
	fmt.Printf("Your name is %s. You are %d years old. Your favourite number is %.2f. %s\n", user.UserName, user.Age, user.FavouriteNumber, ownDogString)

}

func prompt() {
	fmt.Print("-> ")
}

func readString(s string) string {
	for {
		fmt.Println(s)
		prompt()

		userInput, _ := reader.ReadString('\n')
		userInput = strings.Replace(userInput, "\r\n", "", -1)
		userInput = strings.Replace(userInput, "\n", "", -1)

		if userInput == "" {
			fmt.Println("Please enter value")
		} else {
			return userInput
		}
	}
}

func readInt(s string) int {
	for {
		fmt.Println(s)
		prompt()

		userInput, _ := reader.ReadString('\n')
		userInput = strings.Replace(userInput, "\r\n", "", -1)
		userInput = strings.Replace(userInput, "\n", "", -1)

		num, err := strconv.Atoi(userInput)

		if err != nil {
			fmt.Println("Please enter a whole number")
		} else {
			return num
		}
	}
}

func readFloat(s string) float64 {
	for {
		fmt.Println(s)
		prompt()

		userInput, _ := reader.ReadString('\n')
		userInput = strings.Replace(userInput, "\r\n", "", -1)
		userInput = strings.Replace(userInput, "\n", "", -1)

		num, err := strconv.ParseFloat(userInput, 64)

		if err != nil {
			fmt.Println("Please enter a number")
		} else {
			return num
		}
	}
}

func readConfirm(s string) bool {
	for {
		fmt.Print(s)

		char, _, err := keyboard.GetSingleKey()
		fmt.Println("")

		if err != nil {
			fmt.Println("Please enter Yes(y) or No(n).")
			continue
		}

		defer func() {
			_ = keyboard.Close()
		}()

		if char == 'y' || char == 'Y' {
			return true
		} else if char == 'n' || char == 'N' {
			return false
		} else {
			fmt.Println("Please enter Yes(y) or No(n).")
		}
	}
}
